package com.security.granter;

import com.security.constant.AuthConstant;
import com.security.entity.User;
import com.security.entity.UserInfo;
import com.security.feign.ITestUserClient;
import com.security.service.TestUserDetails;
import com.security.util.TokenUtil;
import com.security.util.WebUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.*;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 验证码TokenGranter
 * @author cici
 */
public class CaptchaTokenGranter extends AbstractTokenGranter {

	private final AuthenticationManager authenticationManager;

	private ITestUserClient userClient;

	protected CaptchaTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices,
								  ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType,ITestUserClient userClient) {
		super(tokenServices, clientDetailsService, requestFactory, grantType);
		this.authenticationManager = authenticationManager;
		this.userClient = userClient;
	}

	@Override
	protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
		HttpServletRequest request = WebUtil.getRequest();
		// 增加验证码判断
		String key = request.getHeader(TokenUtil.CAPTCHA_HEADER_KEY);
		String code = request.getHeader(TokenUtil.CAPTCHA_HEADER_CODE);
		// 获取验证码，先自己默认写死
		String redisCode = "123456";
		// 判断验证码
		if (code == null || !StringUtils.equalsIgnoreCase(redisCode, code)) {
			throw new UserDeniedAuthorizationException(TokenUtil.CAPTCHA_NOT_CORRECT);
		}
		// 远程调用返回数据
		Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
		// 手机号
		String phone = parameters.get("username");
		String tenantCode = request.getHeader(TokenUtil.TENANT_HEADER_KEY);
		UserInfo userInfo = userClient.queryUserInfoByUsername(phone);
		// 判断返回信息
		Assert.notNull(userInfo, TokenUtil.USER_NOT_FOUND);
		Assert.notEmpty(userInfo.getRoles(), TokenUtil.USER_HAS_NO_ROLE);

		User user = userInfo.getUser();
		Assert.notNull(user, TokenUtil.USER_NOT_FOUND);

		TestUserDetails userDetails = new TestUserDetails(
				user.getId(),
				user.getName(),
				user.getRealName(),
				user.getAccount(),
				AuthConstant.ENCRYPT + user.getPassword(),
				true,
				true,
				true,
				true,
				AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.join(userInfo.getRoles())));

		List<SimpleGrantedAuthority> authorities = userInfo.getRoles().stream()
				.map(authority->new SimpleGrantedAuthority(authority)).collect(Collectors.toList());

		// 组装认证数据，关闭密码校验
		AbstractAuthenticationToken userAuth = new UsernamePasswordAuthenticationToken(userDetails,
				null, authorities);
		userAuth.setDetails(parameters);
		OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);

		// 返回 OAuth2Authentication
		return new OAuth2Authentication(storedOAuth2Request, userAuth);
	}
}
